//package org.ricks.dispatcher.asm;
//
//import org.ricks.common.lang.Tuple;
//import org.ricks.common.asm.*;
//
//import java.util.Comparator;
//import java.util.List;
//import java.util.Locale;
//import java.util.Set;
//import java.util.stream.Collectors;
//
///**
// * @author ricks
// * @Description: 网络消息分发逻辑
// *
// * 不使用生成 class字节码加载进jvm方式，而是使用asm方法增强模式
// * @date 2022/11/3013:46
// */
//public class DispatcherDump implements Opcodes {
//
//
//
//    public static byte[] dump(List<Tuple> tupleList) throws Exception {
//        Set<String> classNames =  tupleList.stream().map(tuple -> (String)tuple.get(1)).collect(Collectors.toSet()); //对象入口
//        ClassWriter classWriter = new ClassWriter(0);
//        FieldVisitor fieldVisitor;
//        MethodVisitor methodVisitor;
//
//        classWriter.visit(V21, ACC_PUBLIC | ACC_SUPER, "org/ricks/net/dispatcher/EnhanceDispatcher", null, "java/lang/Object", new String[]{"org/ricks/net/dispatcher/Dispatcher"});
//        classWriter.visitSource("EnhanceDispatcher.java", null);
//        classWriter.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC | ACC_FINAL | ACC_STATIC);
//
//        initFieldVisitor(classNames,classWriter);
//
//        {
//            methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
//            methodVisitor.visitCode();
//            Label label0 = new Label();
//            methodVisitor.visitLabel(label0);
//            methodVisitor.visitLineNumber(17, label0);
//            methodVisitor.visitVarInsn(ALOAD, 0);
//            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
//            methodVisitor.visitInsn(RETURN);
//            Label label1 = new Label();
//            methodVisitor.visitLabel(label1);
//            methodVisitor.visitLocalVariable("this", "Lorg/ricks/net/dispatcher/EnhanceDispatcher;", null, label0, label1, 0);
//            methodVisitor.visitMaxs(1, 1);
//            methodVisitor.visitEnd();
//        }
//
//        {
//            methodVisitor = classWriter.visitMethod(ACC_PUBLIC , "dispatcher", "(Lorg/ricks/common/net/Context;)V", "(Lorg/ricks/common/net/Context<Ljava/lang/Short;[B>;)V", null);
//            methodVisitor.visitCode();
////            methodVisitor.visitParameter("context", 0);
//
//            Label label0 = new Label();
//            methodVisitor.visitLabel(label0);
//            methodVisitor.visitLineNumber(23, label0);
//            methodVisitor.visitVarInsn(ALOAD, 1);
//            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/ricks/common/net/Context", "getCmd", "()Ljava/lang/Object;", false);
//            methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/Short");
//            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
//
//            methodVisitor.visitVarInsn(ISTORE, 2);
//            Label label1 = new Label();
//            methodVisitor.visitLabel(label1);
//            methodVisitor.visitLineNumber(24, label1);
//            methodVisitor.visitVarInsn(ILOAD, 2);
//
//            tupleList = tupleList.stream().sorted(Comparator.comparing(tuple -> tuple.get(0))).collect(Collectors.toList()); //妈的，浪费老子那么多时间。switch 必须要从小到大排序不然生成的class字节码会进入 default 默认。fuck you
//            int[] messageIds = new int[tupleList.size()];
//            Label[] labels = new Label[tupleList.size()];
//            for (int i = 0; i < tupleList.size(); i++) {
//                labels[i] = new Label();
//                messageIds[i] = Integer.valueOf(tupleList.get(i).get(0).toString());
//            }
//            Label defaultLabel  = new Label();
//            Label gotoLabel  = new Label();
//            methodVisitor.visitLookupSwitchInsn(defaultLabel, messageIds, labels);
//            int currLineNum = 24;
//            for (int i = 0; i < tupleList.size(); i++) {
//                currLineNum += 1;
//                createMethodFunction(methodVisitor,tupleList.get(i), labels[i],currLineNum,gotoLabel,i==0);
//            }
//
//            methodVisitor.visitLabel(defaultLabel);
//            methodVisitor.visitLineNumber(currLineNum + 1, defaultLabel);
//            methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
//            methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
//            methodVisitor.visitVarInsn(ALOAD, 1);
//            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/ricks/common/net/Context", "getCmd", "()Ljava/lang/Object;", false);
//            methodVisitor.visitInvokeDynamicInsn("makeConcatWithConstants", "(Ljava/lang/Object;)Ljava/lang/String;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/StringConcatFactory", "makeConcatWithConstants", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;", false), new Object[]{"\u0001 \u672a\u77e5\u6307\u4ee4"});
//            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
//            methodVisitor.visitLabel(gotoLabel);
//            methodVisitor.visitLineNumber(currLineNum + 5, gotoLabel);
//            methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
//            methodVisitor.visitInsn(RETURN);
//            Label label14 = new Label();
//            methodVisitor.visitLabel(label14);
//            methodVisitor.visitLocalVariable("this", "Lorg/ricks/dispatcher/EnhanceDispatcher;", null, label0, label14, 0);
//            methodVisitor.visitLocalVariable("context", "Lorg/ricks/common/net/Context;", "(Lorg/ricks/common/net/Context<Ljava/lang/Short;[B>;)V", label0, label14, 1);
//            methodVisitor.visitLocalVariable("cmd", "S", null, label1, label14, 2);
//            methodVisitor.visitMaxs(2, 3);
//            methodVisitor.visitEnd();
//        }
//
//        {
//            methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
//            methodVisitor.visitCode();
//            createEnd(methodVisitor,classNames);
//
//            methodVisitor.visitInsn(RETURN);
//            methodVisitor.visitMaxs(1, 0);
//            methodVisitor.visitEnd();
//        }
//
//        classWriter.visitEnd();
//
//        return classWriter.toByteArray();
//    }
//
//
//
//    private static FieldVisitor initFieldVisitor(Set<String> classNames, ClassWriter classWriter) {
//        FieldVisitor fieldVisitor = null;
//        for (String className : classNames) {
//            String objName = className.substring(className.lastIndexOf(".") + 1,className.length()).toLowerCase(Locale.ROOT);
//            String cName = className.replace(".","/");
//            fieldVisitor = classWriter.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, objName, "L"+cName+";", null, null);
//            fieldVisitor.visitEnd();
//        }
//        return fieldVisitor;
//    }
//
//    private static void  createMethodFunction(MethodVisitor methodVisitor, Tuple tuple, Label label, int lineNum, Label gotoLabel,boolean isFirst) {
//        String className = tuple.get(1).toString();
//        String cName = className.replace(".","/");
//        String objName = className.substring(className.lastIndexOf(".") + 1,className.length()).toLowerCase(Locale.ROOT);
//        methodVisitor.visitLabel(label);
//        methodVisitor.visitLineNumber(lineNum, label);
//        if(isFirst) methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[]{Opcodes.INTEGER}, 0, null); else methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
//        methodVisitor.visitFieldInsn(GETSTATIC, "org/ricks/net/dispatcher/EnhanceDispatcher", objName, "L"+cName+";");
//        methodVisitor.visitVarInsn(ALOAD, 1);
//        methodVisitor.visitMethodInsn(INVOKEVIRTUAL, cName, tuple.get(2), "(Lorg/ricks/common/net/Context;)V", false);
//
////        methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
////        methodVisitor.visitLdcInsn("\u8fdb\u5165\u539f\u751f\u6001\u3002\u3002\u3002\u3002\u3002\u3002\u3002\u3002");
////        methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
//
//        methodVisitor.visitJumpInsn(GOTO, gotoLabel);
//
//    }
//
//    private static void createEnd(MethodVisitor methodVisitor,Set<String> classNames) {
//        int line = 19;
//        for (String className : classNames) {
//            String objName = className.substring(className.lastIndexOf(".") + 1,className.length()).toLowerCase(Locale.ROOT);
//            String cName = className.replace(".","/");
//            Label label0 = new Label();
//            methodVisitor.visitLabel(label0);
//            methodVisitor.visitLineNumber(line, label0);
//            methodVisitor.visitLdcInsn(Type.getType("L"+cName+";"));
//            methodVisitor.visitMethodInsn(INVOKESTATIC, "org/ricks/ioc/IocHolder", "getBean", "(Ljava/lang/Class;)Ljava/lang/Object;", false);
//            methodVisitor.visitTypeInsn(CHECKCAST, cName);
//            methodVisitor.visitFieldInsn(PUTSTATIC, "org/ricks/net/dispatcher/EnhanceDispatcher", objName, "L"+cName+";");
//            line += 1;
//        }
//
//    }
//}
